<script setup>
import { ref, computed, watch, onMounted, onBeforeUnmount } from 'vue'

const props = defineProps({
  position: {
    type: String,
    default: 'left',
    validator: v => ['left', 'right'].includes(v)
  },
  width: {
    type: [String, Number],
    default: '300px'
  },
  collapsible: {
    type: Boolean,
    default: true
  },
  defaultCollapsed: {
    type: Boolean,
    default: false
  },
  showOverlay: {
    type: Boolean,
    default: true
  },
  overlayOpacity: {
    type: Number,
    default: 0.5
  },
  closeOnClickOutside: {
    type: Boolean,
    default: true
  },
  preventScroll: {
    type: Boolean,
    default: true
  },
  animationType: {
    type: String,
    default: 'slide',
    validator: v => ['slide', 'fade', 'none'].includes(v)
  },
  animationDuration: {
    type: Number,
    default: 300
  },
  responsive: {
    type: Boolean,
    default: true
  },
  breakpoint: {
    type: Number,
    default: 768
  },
  modelValue: {
    type: Boolean,
    required: true
  }
})

const emit = defineEmits(['update:modelValue', 'open', 'close', 'toggle', 'overlay-click'])

// 计算样式
const sidebarStyles = computed(() => ({
  width: typeof props.width === 'number' ? `${props.width}px` : props.width,
  '--animation-duration': `${props.animationDuration}ms`
}))

const overlayStyles = computed(() => ({
  backgroundColor: `rgba(0, 0, 0, ${props.overlayOpacity})`
}))

// 处理遮罩点击
const handleOverlayClick = () => {
  if (props.closeOnClickOutside) {
    emit('update:modelValue', false)
    emit('overlay-click')
  }
}

// 响应式处理
onMounted(() => {
  if (props.responsive) {
    window.addEventListener('resize', handleResize)
  }
  if (props.preventScroll) {
    document.body.style.overflow = props.modelValue ? 'hidden' : ''
  }
})

onBeforeUnmount(() => {
  if (props.responsive) {
    window.removeEventListener('resize', handleResize)
  }
  if (props.preventScroll) {
    document.body.style.overflow = ''
  }
})

const handleResize = () => {
  if (window.innerWidth < props.breakpoint && props.modelValue) {
    emit('update:modelValue', false)
  }
}

// 监听状态变化
watch(() => props.modelValue, (val) => {
  if (props.preventScroll) {
    document.body.style.overflow = val ? 'hidden' : ''
  }
  emit(val ? 'open' : 'close')
})
</script>

<template>
  <transition :name="animationType" :duration="animationDuration">
    <div v-show="modelValue" class="sidebar-container">
      <div
          class="sidebar"
          :class="[`sidebar-${position}`, { collapsible }]"
          :style="sidebarStyles"
      >
        <slot name="header"></slot>
        <div class="sidebar-content">
          <slot></slot>
        </div>
        <slot name="footer"></slot>
      </div>
      <div
          v-if="showOverlay"
          class="sidebar-overlay"
          :style="overlayStyles"
          @click="handleOverlayClick"
      ></div>
    </div>
  </transition>
</template>

<style scoped>
.sidebar-container {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1000;
}

.sidebar {
  position: fixed;
  top: 0;
  bottom: 0;
  background: #fff;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
  z-index: 1001;
}

.sidebar-left { left: 0; }
.sidebar-right { right: 0; }

.sidebar-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  z-index: 1000;
}

.slide-enter-active,
.slide-leave-active {
  transition: transform var(--animation-duration) ease;
}

.slide-enter-from.sidebar-left,
.slide-leave-to.sidebar-left {
  transform: translateX(-100%);
}

.slide-enter-from.sidebar-right,
.slide-leave-to.sidebar-right {
  transform: translateX(100%);
}

.fade-enter-active,
.fade-leave-active {
  transition: opacity var(--animation-duration) ease;
}

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}
</style>